﻿using System;
using System.Drawing;
using System.Drawing.Imaging;

namespace PO_2011.ColorConvert
{
    class Colors : BitmapFastPixel
    {
        public static Bitmap convertBitmapColorToGrey(Bitmap image, int type)
        {
            if(image.PixelFormat == PixelFormat.Format32bppArgb)
            {
                Bitmap image_grey = new Bitmap(image.Width, image.Height);
                Color color;
                int color_char;

                for (int y = 0; y < image.Height; y++)
                {
                    for (int x = 0; x < image.Width; x++)
                    {
                        if (type == 1)
                        {
                            color_char = (int) convertFromColorToGray(image.GetPixel(x, y));
                            color = Color.FromArgb(color_char, color_char, color_char);
                            image_grey.SetPixel(x, y, color);
                        }
                    }
                }

                return image_grey;
            }
            else
            {
                return image;
            }
        }

        public static Bitmap convertFromColorToBlack(Bitmap image, String new_type, String old_type)
        {
            if ((old_type == "P1") || (old_type == "P4"))
            {
                return image;
            }

            old_img = image;
            char one_color;
            int black = 90;

            for (int x = 0; x < old_img.Width; x++)
            {
                for (int y = 0; y < old_img.Height; y++)
                {
                    if ((new_type == old_type) | (new_type == "P1" && old_type == "P4"))
                    {
                        one_color = getFastPixel(x, y)[0] == 255 ? '1' : '0';
                    }
                    else if (old_type == "P2" | old_type == "P5")
                    {
                        one_color = (Char)getFastPixel(x, y)[0] < black ? '1' : '0';
                    }
                    else
                    {
                        int [] color = getFastPixel(x, y);
                        one_color = (int)convertFromColorToGray(Color.FromArgb(color[0], color[1], color[2]), new_type, old_type) < black + 40 ? '1' : '0';
                    }

                    setFastPixel(x, y, one_color, one_color, one_color);
                }
            }


            return getNewImage(true);
        }


        public static char convertFromColorToBlack(Color color, String new_type, String old_type)
        {
            char one_color;
            int black = 90;
            if ((new_type == old_type) | (new_type == "P1" && old_type == "P4"))
            {
                one_color = color.R == 255 ? '1' : '0';
            }
            else if (old_type == "P2" | old_type == "P5")
            {
                one_color = (int)color.R < black ? '1' : '0';
            }
            else
            {
                one_color = (int)convertFromColorToGray(color, new_type, old_type) < black + 40 ? '1' : '0';
            }

            return one_color;
        }

        public static char convertFromColorToGray(Color color, String new_type = "", String old_type = "")
        {
            return (char)(0.21 * color.R + 0.71 * color.G + 0.07 * color.B);
        }

        public static Bitmap convertRGBtoCMYK(Bitmap inputImage)
        {
            old_img = inputImage;
            int[] pColors;
            float colorC, colorM, colorY, colorK;

            for (int y = 0; y < inputImage.Height; y++)
            {
                for (int x = 0; x < inputImage.Width; x++)
                {
                    pColors = getFastPixel(x, y);

                    colorC = (float)(255 - pColors[0]) / 255;
                    colorM = (float)(255 - pColors[1]) / 255;
                    colorY = (float)(255 - pColors[2]) / 255;
                    colorK = (float)Math.Min(colorC, Math.Min(colorM, colorY));

                    if (colorK == 1.0)
                    {
                        colorC = 0;
                        colorM = 0;
                        colorY = 0;
                    }
                    else
                    {
                        colorC = (colorC - colorK) / (1 - colorK);
                        colorM = (colorM - colorK) / (1 - colorK);
                        colorY = (colorM - colorK) / (1 - colorK);
                    }

                    int CMYKtoR = (int)((1 - colorC) * (1 - colorK) * 255.0);
                    int CMYKtoG = (int)((1 - colorM) * (1 - colorK) * 255.0);
                    int CMYKtoB = (int)((1 - colorY) * (1 - colorK) * 255.0);

                    setFastPixel(x, y, CMYKtoR, CMYKtoG, CMYKtoB);
                }
            }

            return getNewImage(true);
        }

        public static Bitmap changeBrightness(Bitmap inputImage, int val, int maxVal)
        {
            old_img = inputImage;
            int[] pColors;

            for (int x = 0; x < old_img.Width; x++)
            {
                for (int y = 0; y < old_img.Height; y++)
                {
                    pColors = getFastPixel(x, y);

                    for (int i = 0; i < 3; i++)
                    {
                        pColors[i] += val * (255 / maxVal);
                        if (pColors[i] > 255) pColors[i] = 255;
                        if (pColors[i] < 0) pColors[i] = 0;
                    }

                    setFastPixel(x, y, pColors[0], pColors[1], pColors[2]);
                }
            }

            return getNewImage(true);
        }

        public static Bitmap changeContrast(Bitmap inputImage, int val, int maxVal)
        {
            old_img = inputImage;
            int[] pColors;

            double contrast = (maxVal + val) / (double)maxVal;
            contrast *= contrast;

            for (int x = 0; x < old_img.Width; x++)
            {
                for (int y = 0; y < old_img.Height; y++)
                {
                    pColors = getFastPixel(x, y);

                    for (int i = 0; i < 3; i++)
                    {
                        pColors[i] = (int)(((((pColors[i] / 255.0) - 0.5) * contrast) + 0.5) * 255);
                        if (pColors[i] < 0) pColors[i] = 0;
                        if (pColors[i] > 255) pColors[i] = 255;
                    }

                    setFastPixel(x, y, pColors[0], pColors[1], pColors[2]);
                }
            }

            return getNewImage(true);
        }

        public static Bitmap changeGamma(Bitmap inputImage, double val)
        {
            old_img = inputImage;
            int[] pColors;

            int[] gammaLUT = new int[256];
            val = val < 10 ? (val + 1) / 10 : 1 + (val - 9) * 0.5; // sprowadzamy wartość gamma do przedzału <0.2; 5>
            
            for (int i = 0; i < 256; ++i)
            {
                gammaLUT[i] = (int)((255.0 * Math.Pow(i / 255.0, 1.0 / val)) + 0.5);
                if (gammaLUT[i] > 255) gammaLUT[i] = 255;
            }

            for (int x = 0; x < old_img.Width; x++)
            {
                for (int y = 0; y < old_img.Height; y++)
                {
                    pColors = getFastPixel(x, y);

                    pColors[0] = gammaLUT[pColors[0]];
                    pColors[1] = gammaLUT[pColors[1]];
                    pColors[2] = gammaLUT[pColors[2]];

                    setFastPixel(x, y, pColors[0], pColors[1], pColors[2]);
                }
            }

            return getNewImage(true);
        }

    }
}
